package com.ccl.iot.privates;

import com.ccl.iot.publics.XCoreKernel;

public class WaveCalculator {
	private LinearFilter iFilter;
	
	private float iRange;
	private long iInterval;
	
	private int iChanged = 0;
	private long iLastTime = 0;
	private boolean iRaising = false;
	private int iKeepStep = 0;
	private float iLastValue = 0;
	private float iMinValue = 0;
	private long iMinTime = 0;
	private float iMaxValue = 0;
	private long iMaxTime = 0;
	
	public WaveCalculator(LinearFilter aFilter){
		iFilter = aFilter;
	}
	
	public void reset(){
		iRange = 0;
		iInterval = 0;
		iKeepStep = 0;
	}
	
	public boolean put(float aValue){
		boolean tRet = false;
		long tTime = XCoreKernel.SYSTICKCOUNT();
		
		if (iFilter != null){
			aValue = iFilter.put(aValue);
		}
		
		if (iChanged > 0){
			boolean tRaising = (aValue == iLastValue ? iRaising : (aValue > iLastValue));
			
			if (tRaising == iRaising){
				if (++iKeepStep == 1){
					if (tRaising){
						iMinValue = iLastValue;
						iMinTime = iLastTime;
					}else{
						iMaxValue = iLastValue;
						iMaxTime = iLastTime;
					}
				}else{
					if (tRaising){
						if (aValue > iMaxValue){
							iMaxValue = aValue;
							iMaxTime = tTime;
						}
					}else{
						if (aValue < iMinValue){
							iMinValue = aValue;
							iMinTime = tTime;
						}
					}
				}
			}else{
				float tRange;
				long tInterval;
				
				if (iRaising){
					tRange = iLastValue - iMinValue;
					tInterval = XCoreKernel.GetTickInterval(iMinTime, iLastTime);
					
					iMinValue = iLastValue;
					iMinTime = iLastTime;
				}else{
					tRange = iMaxValue - iLastValue;
					tInterval = XCoreKernel.GetTickInterval(iMaxTime, iLastTime);
					
					iMaxValue = iLastValue;
					iMaxTime = iLastTime;
				}
				
				if (tRange != iRange || tInterval != iInterval){
					iRange = tRange;
					iInterval = tInterval;
					
					tRet = true;
				}
				
				iRaising = tRaising;
				
				iKeepStep = 0;
			}
		}else{
			iKeepStep = 0;
			
			tRet = true;
		}
		
		if (iChanged < Integer.MAX_VALUE){
			iChanged++;
		}
		
		iLastValue = aValue;
		
		iLastTime = tTime;
		
		return tRet;
	}
	
	public float getRange(){
		return iRange;
	}
	
	public long getInterval(){
		return iInterval;
	}
}
